﻿using System;
using System.Diagnostics;
using UnityEngine;

namespace Runtime.Services.Battle {

    /// <summary>
    /// 战斗单元格坐标
    /// </summary>
    [Serializable]
    [DebuggerStepThrough]
    [DebuggerNonUserCode]
    public readonly struct DFR_BattleCellAxis {

        public static readonly DFR_BattleCellAxis Invalid = new() { X = int.MinValue, Y = int.MinValue };

        /// <summary>
        /// X
        /// </summary>
        [SerializeField]
        private readonly int m_X;
        public int X { get => m_X; init => m_X = value; }

        /// <summary>
        /// Y
        /// </summary>
        [SerializeField]
        private readonly int m_Y;
        public int Y { get => m_Y; init => m_Y = value; }

        public DFR_BattleCellIndex ToIndex() => new() {
            Value = (int)BattleServiceBase.Instance.HorizontalCellCount * (Y + (int)BattleServiceBase.Instance.VerticalCellCount / 2) + (X + (int)BattleServiceBase.Instance.HorizontalCellCount / 2)
        };

        public override bool Equals(object obj) {
            if (obj is DFR_BattleCellAxis other) {
                return other.X == X && other.Y == Y;
            }
            return false;
        }

        public override string ToString() => $"[{nameof(DFR_BattleCellAxis)}({nameof(X)}={X},{nameof(Y)}={Y})]";

        public override int GetHashCode() => HashCode.Combine(X, Y);

        public static float Distance(DFR_BattleCellAxis a, DFR_BattleCellAxis b) => Vector2.Distance((Vector2)a, (Vector2)b);

        public static bool operator ==(DFR_BattleCellAxis left, DFR_BattleCellAxis right) => left.Equals(right);
        public static bool operator !=(DFR_BattleCellAxis left, DFR_BattleCellAxis right) => !left.Equals(right);

        public static implicit operator Vector3(DFR_BattleCellAxis @in) => new(@in.X, @in.Y);
        public static implicit operator Vector3Int(DFR_BattleCellAxis @in) => new(@in.X, @in.Y);
        public static implicit operator Vector3F64(DFR_BattleCellAxis @in) => Vector3F64.FromRaw(@in.X, @in.Y, 0);

        public static implicit operator Vector2(DFR_BattleCellAxis @in) => new(@in.X, @in.Y);
        public static implicit operator Vector2Int(DFR_BattleCellAxis @in) => new(@in.X, @in.Y);
        public static implicit operator Vector2F64(DFR_BattleCellAxis @in) => Vector2F64.From(@in.X, @in.Y);

        public static implicit operator DFR_BattleCellAxis(Vector3Int @in) => new() { X = @in.x, Y = @in.y };
        public static implicit operator DFR_BattleCellAxis(Vector2Int @in) => new() { X = @in.x, Y = @in.y };

        public static explicit operator DFR_BattleCellAxis(DFR_BattleMapPosition @in) => new() { X = @in.X.Int, Y = @in.Y.Int };
    }
}
